package dfl.bysj.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.oracle.deploy.update.UpdateInfo;
import dfl.bysj.config.RedisKey;
import dfl.bysj.config.model.VO.UserDto;
import dfl.bysj.entity.*;
import dfl.bysj.entity.VO.TeacherVO;
import dfl.bysj.entity.VO.UpdateBindVO;
import dfl.bysj.entity.VO.UpdateInformationVO;
import dfl.bysj.exception.Assert;
import dfl.bysj.exception.UnifiedException;
import dfl.bysj.mapper.TeacherMapper;
import dfl.bysj.mapper.UserMapper;
import dfl.bysj.mapper.UserTeacherStudentMapper;
import dfl.bysj.result.ResponseEnum;
import dfl.bysj.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import dfl.bysj.util.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author DFL
 * @since 2022-04-26
 */
@Slf4j
@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {

    TeacherMapper teacherMapper;

    UserMapper userMapper;

    UserTeacherStudentMapper userTeacherStudentMapper;

    RedisTemplate redisTemplate;

    UserService userService;

    private UpdateInformationService updateInformationService;

    private StudentService studentService;
    private UpdateBindService updateBindService;

    private HonestStudentService honestStudentService;
    private List<Teacher> teachers;

    private HonestGradeService honestGradeService;

    private StudentSeatRelationService studentSeatRelationService;

    @Autowired
    public void setStudentSeatRelationService(StudentSeatRelationService studentSeatRelationService) {
        this.studentSeatRelationService = studentSeatRelationService;
    }

    @Autowired
    public void setHonestGradeService(HonestGradeService honestGradeService) {
        this.honestGradeService = honestGradeService;
    }

    @Autowired
    public void setHonestStudentService(HonestStudentService honestStudentService) {
        this.honestStudentService = honestStudentService;
    }

    private AtomicReference<Teacher> teacherAtomicReference= new AtomicReference<>(new Teacher());

    @Autowired
    public void setUpdateInformationService(UpdateInformationService updateInformationService) {
        this.updateInformationService = updateInformationService;
    }

    @Autowired
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }

    @Autowired
    public void setUpdateBindService(UpdateBindService updateBindService) {
        this.updateBindService = updateBindService;
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Autowired
    public void setUserTeacherStudentMapper(UserTeacherStudentMapper userTeacherStudentMapper) {
        this.userTeacherStudentMapper = userTeacherStudentMapper;
    }

    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Autowired
    public void setTeacherMapper(TeacherMapper teacherMapper) {
        this.teacherMapper = teacherMapper;
    }



    private void getTeachers(){
        teachers= (List<Teacher>) redisTemplate.opsForValue().get(RedisKey.ALL_TEACHER);
        if (teachers==null){
            updateRedisOfTeachers();

        }
    }

    private void updateRedisOfTeachers(){
        teachers=list();
        redisTemplate.opsForValue().set(RedisKey.ALL_TEACHER,teachers,7, TimeUnit.DAYS);
    }

    @Override
    public Teacher getTeacherByName_Phone(TeacherVO teacherVO) {
        getTeachers();
        teachers.stream()
                .filter(s->s.getTeaName().equals(teacherVO.getTeaName()))
                .filter(s->s.getTeaPhone().equals(teacherVO.getTeaPhone()))
                .forEach(s->teacherAtomicReference.set(s));

        if (teacherAtomicReference.get()==null){
            return null;
        }
        return teacherAtomicReference.get();
    }
    @Override
    public Object regist(TeacherVO teacherVO) {
        /**
         * 封装Student信息
         */
        Teacher teacher=new Teacher(teacherVO.getTeaName(), teacherVO.getTeaPhone().intValue());
        /**
         * 封装完以后，不是插入Student，而是比对student信息，
         * 1、信息一致
         * 2、默认审核通过
         * 如果信息一致，将对应信息插入用户学生关系表，返回审核通过
         */
        Teacher teacher1=getTeacherByName_Phone(teacherVO);

        //信息不一致就返回错误信息
        Assert.notNull(teacher1, ResponseEnum.STUDENT_TEACHER_INFORMATION_NOT_EQUAL);
        //信息一致：将信息插入关系表，创造token，保存信息到redis
        //1、将信息插入关系表
        UserTeacherStudent userTeacherStudent=new UserTeacherStudent();
        userTeacherStudent.setTeaId(teacher1.getTeaId());
        //通过openId查询用户表，获取用户id
        log.info("openId："+teacherVO.getOpenId());
        User user=userService.getUserByOpenId(teacherVO.getOpenId());
        userTeacherStudent.setUseId(user.getId());

        //暂时给予审核通过
        userTeacherStudent.setCheckState(true);
        //插入关系表
        int result=userTeacherStudentMapper.insert(userTeacherStudent);


        //2、创造token
        String token= JWTUtils.sign(user.getId());
        //3、保存信息到redis
        UserDto userDto=new UserDto();
        userDto.setUser(user);
        userDto.setTeacher(teacher);



        redisTemplate.opsForValue().set(RedisKey.TOKEN+token, JSON.toJSONString(userDto),7, TimeUnit.DAYS);

        return result;
    }

    @Override
    public ArrayList<UpdateBindVO> getAllUpdateBindVO() {
        ArrayList<UpdateBind> updateBinds= (ArrayList<UpdateBind>) updateBindService.getAllUpdateBind();
        Assert.notNull(updateBinds, ResponseEnum.UPDATE_BIND_NULL);
        ArrayList<UpdateBindVO> updateBindVOS=new ArrayList<>();
        updateBinds.stream().forEach(s->{
            UpdateBindVO updateBindVO=new UpdateBindVO( studentService.getStudentById(s.getBeforeStuId()),
                    studentService.getStudentById(s.getAfterStuId()),
                    userService.getUserById(s.getUseId()));
            updateBindVOS.add(updateBindVO);

        });
        return updateBindVOS;
    }

    /**
     * 通过审核
     *       1、通过useid获取修改表
     *       2、删除表
     *       3、修改关系表中的绑定
     *          1、新增关系
     *          2、修改权限
     * @param use_id
     */
    @Override
    public void passCheck(Integer use_id) {
        UpdateBind updateBind=updateBindService.getUpdateBindByUseId(use_id);
        updateBindService.deleteUpdateBindByUseId(use_id);

        UserTeacherStudent userTeacherStudent=new UserTeacherStudent();

        userTeacherStudent.setCheckState(false);
        userTeacherStudentMapper.update(userTeacherStudent,
                new QueryWrapper<UserTeacherStudent>()
                        .eq("use_id", updateBind.getUseId()));


        UserTeacherStudent finalUserTeacherStudent = userTeacherStudent;
        Thread thread=new Thread(()->{
            finalUserTeacherStudent.setStuId(updateBind.getAfterStuId());
            finalUserTeacherStudent.setUseId(updateBind.getUseId());
            finalUserTeacherStudent.setCheckState(true);
            userTeacherStudentMapper.insert(finalUserTeacherStudent);
        });

        thread.start();
        try {
            thread.join();
        }catch (Exception e){
            throw new UnifiedException(ResponseEnum.ERROR);
        }

        userTeacherStudent=userTeacherStudentMapper.selectOne(new QueryWrapper<UserTeacherStudent>()
                .eq("use_id", updateBind.getUseId())
                .eq("stu_id", updateBind.getAfterStuId())
                .eq("check_state", true));

        //转信用记录
        HonestStudent honestStudent=new HonestStudent();
        honestStudent.setStuUseId(userTeacherStudent.getStuUseId());
        honestStudentService.update(honestStudent, new QueryWrapper<HonestStudent>()
                .eq("stu_use_id",updateBind.getBeforeStuUseId()));

        //转信用分
        HonestGrade honestGrade=new HonestGrade();
        honestGrade.setStuUseId(userTeacherStudent.getStuUseId());
        honestGradeService.updateHonestGradeByStuUseId(honestGrade,updateBind.getBeforeStuUseId());

        StudentSeatRelation studentSeatRelation=new StudentSeatRelation();
        studentSeatRelation.setStuUseId(userTeacherStudent.getStuUseId());
        log.info("userTeacherStudent::{}----{}",userTeacherStudent.getStuUseId(),updateBind.getBeforeStuUseId());

        studentSeatRelationService.update(studentSeatRelation,new QueryWrapper<StudentSeatRelation>()
                .eq("stu_use_id", updateBind.getBeforeStuUseId()));
    }

    /**
     * 审核不通过
     * 1、获取updateBind的内容
     * 2、删除
     * 3、将updateBind中原来的stuid 和 用户id重新绑定
     * 4、通过授权
     * @param use_id
     */
    @Override
    public void denyCheck(Integer use_id) {
        UpdateBind updateBind=updateBindService.getUpdateBindByUseId(use_id);
        updateBindService.deleteUpdateBindByUseId(use_id);

        UserTeacherStudent userTeacherStudent=new UserTeacherStudent();

        userTeacherStudent.setCheckState(false);
        userTeacherStudentMapper.update(userTeacherStudent,
                new QueryWrapper<UserTeacherStudent>()
                        .eq("use_id", updateBind.getUseId()));


        userTeacherStudent.setCheckState(true);
        userTeacherStudent.setStuId(updateBind.getBeforeStuId());
        userTeacherStudent.setUseId(updateBind.getUseId());
        userTeacherStudentMapper.update(userTeacherStudent,new QueryWrapper<UserTeacherStudent>()
                .eq("use_id", updateBind.getUseId())
                .eq("stu_id", updateBind.getBeforeStuId())
                .orderByDesc("update_time")
                .last("limit 1"));
    }

    @Override
    public ArrayList<UpdateInformationVO> getAllUpdateInformationVO() {
        ArrayList<UpdateInformation> updateInformations= (ArrayList<UpdateInformation>) updateInformationService.list();
        Assert.notNull(updateInformations, ResponseEnum.UPDATE_BIND_NULL);
        ArrayList<UpdateInformationVO> updateInformationVOS=new ArrayList<>();
        updateInformations.stream()
                .filter(s->s.getPassState().equals(3))
                .forEach(s->{
            UpdateInformationVO updateInformationVO=new UpdateInformationVO(
                    studentService.getStudentById(s.getStuId()),
                    s,userService.getUserById(s.getUseId()));
            updateInformationVOS.add(updateInformationVO);

        });
        return updateInformationVOS;
    }

    /**
     * 修改通过
     * 1、修改修改表的状态
     * 2、修改student表的相对应内容
     * @param use_id
     */
    @Override
    public void passCheckInformation(int use_id) {

        UpdateInformation updateInformation1=updateInformationService.getOne(
                new QueryWrapper<UpdateInformation>()
                        .eq("use_id", use_id)
                        .eq("pass_state", 3));

        UpdateInformation updateInformation=new UpdateInformation();
        updateInformation.setPassState(1);
        updateInformationService.update(updateInformation,
                new QueryWrapper<UpdateInformation>()
                        .eq("use_id", use_id)
                        .eq("pass_state", 3));

        Student student=new Student();
        student.setStuName(updateInformation1.getStuName());
        student.setStuPhone(updateInformation1.getStuPhone());
        student.setGraId(updateInformation1.getGraId());
        studentService.updateStudentById(updateInformation1.getStuId(),student);
    }

    /**
     * 拒绝通过
     * 1、修改通过状态
     * @param use_id
     */
    @Override
    public void denyCheckInformation(int use_id) {
        UpdateInformation updateInformation=new UpdateInformation();
        updateInformation.setPassState(2);
        updateInformationService.update(updateInformation,
                new QueryWrapper<UpdateInformation>()
                        .eq("use_id", use_id)
                        .eq("pass_state", 3));
    }


}
